using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using TEngine;

namespace GameLogic
{
    /// <summary>
    /// 可绑定数据对象基类，支持属性变更通知
    /// </summary>
    public abstract class BindableVO : IMemory
    {
        private ActorEventDispatcher _eventDispatcher;

        // 用于存储属性变更事件ID的字典
        private Dictionary<string, int> _propertyEventIds = new Dictionary<string, int>();

        private ActorEventDispatcher EventDispatcher
        {
            get
            {
                if (_eventDispatcher == null)
                {
                    _eventDispatcher = MemoryPool.Acquire<ActorEventDispatcher>();
                }
                return _eventDispatcher;
            }
        }

        /// <summary>
        /// 获取属性变更事件ID
        /// </summary>
        private int GetPropertyEventId(string propertyName)
        {
            if (!_propertyEventIds.TryGetValue(propertyName, out var eventId))
            {
                // 使用对象引用和属性名组合生成唯一事件ID
                eventId = RuntimeId.ToRuntimeId($"{GetType().Name}_{RuntimeHelpers.GetHashCode(this)}_{propertyName}_Changed");
                _propertyEventIds[propertyName] = eventId;
            }
            return eventId;
        }
        /// <summary>
        /// 设置属性值并触发变更事件
        /// </summary>
        protected void SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
        {
            if (EqualityComparer<T>.Default.Equals(field, value))
                return;
            T old = field;
            field = value;
            EventDispatcher.SendEvent(GetPropertyEventId(propertyName), old, value);
        }

        /// <summary>
        /// 监听属性变更
        /// </summary>
        public void AddPropertyListener<T>(string propertyName, Action<T, T> handler, object owner = null)
        {
            EventDispatcher.AddEventListener(GetPropertyEventId(propertyName), handler, owner ?? this);
        }

        /// <summary>
        /// 移除属性变更监听
        /// </summary>
        public void RemovePropertyListener<T>(string propertyName, Action<T, T> handler)
        {
            EventDispatcher.RemoveEventListener(GetPropertyEventId(propertyName), handler);
        }

        /// <summary>
        /// 移除所有监听
        /// </summary>
        public virtual void Clear()
        {
            _eventDispatcher.DestroyAllEventListener();
            _propertyEventIds.Clear();
            MemoryPool.Release(_eventDispatcher);
            _eventDispatcher = null;
        }
    }
}